package tasks

import (
	"errors"
	"strings"

	"torler.com/qingyue/apps/spider/internal/core/task"
	"torler.com/qingyue/apps/spider/internal/site"
	"torler.com/qingyue/common/model"
	"torler.com/qingyue/common/types"
)

const (
	RUNNER_SPIDER_CBOOK = types.RunnerName("spider_cbook_info_task")
	TASK_SPIDER_CBOOK   = types.TaskName("渠道小说爬虫任务")
)

// 渠道小说信息抓取任务
type CBookInfoSpider struct {
}

// 任务执行者预加载
func (it *CBookInfoSpider) Preload(t *task.Task) error {
	return nil
}

func NewCBookInfoSpider() *CBookInfoSpider {
	return &CBookInfoSpider{}
}

// 任务执行者的唯一名称标识用于反序列化
func (it *CBookInfoSpider) Name() types.RunnerName {
	return RUNNER_SPIDER_CBOOK
}

// 任务执行者
func (it *CBookInfoSpider) Run(tsk *task.Task) error {
	db := tsk.GetCtx().DB
	oId := task.GetParam[types.OriginId](tsk, "oid")
	siteId := task.GetParam[types.SourceId](tsk, "site_id")
	var oldBook *model.RawBook
	tx := db.Where(model.RawBook{OId: oId, SourceId: siteId}).FirstOrCreate(&oldBook)
	if tx.Error != nil {
		return tx.Error
	}
	parser := site.GetParserBySiteId(oldBook.SourceId)
	if parser == nil {
		return errors.New("获取解析器失败")
	}

	page, _ := browser.NewPage()
	defer page.Close()
	url := parser.GetBookInfoUrl(oldBook.OId)
	page.Goto(url)

	book, err := parser.ParseBookInfo(page)
	if err != nil {
		return errors.New("解析小说信息失败:" + url)
	}

	oldBook.Author = book.Author
	oldBook.BookName = clearBookName(book.BookName)
	oldBook.CategoryName = book.CategoryName

	desc := clearDesc(book.Desc)
	//去除简介结尾中的书名
	desc = strings.TrimSuffix(desc, book.BookName)
	oldBook.Desc = desc
	oldBook.ChapterCount = book.ChapterCount
	oldBook.WriteState = book.WriteState
	oldBook.LastUpdateTime = book.LastUpdateTime
	oldBook.ImgUrl = book.ImgUrl
	addCount := len(book.Chapters) - len(oldBook.Chapters)
	if addCount > 0 {
		oldBook.Chapters = book.Chapters
		oldBook.ChapterCount = len(book.Chapters)
	}

	oldBook.Spate = types.SpateDone
	tx = db.Save(oldBook)
	if tx.Error != nil {
		return tx.Error
	}
	tsk.SetResult("新增章节数", addCount).SetResult("总章节数", oldBook.ChapterCount)

	return nil

}
